package service

import (
	"context"
	"errors"
	"gorm.io/gorm"
	"shop-bean/constant"
	"shop-bean/model"
	"shop-common/library/variables"
	"shop-common/utils/pagehelper"
	"shop-common/utils/queryWrapper"
	"shop-service/cache"
	"shop-service/repository"
	"time"
)

type IIndexImgService interface {
	Create(ctx context.Context, category *model.IndexImg) error
	FindPage(ctx context.Context, paginator *pagehelper.Paginator) (*pagehelper.Record, error)
	FindOne(ctx context.Context, pair *queryWrapper.WherePair) (*model.IndexImg, error)
	FindById(ctx context.Context, imgId uint) (*model.IndexImg, error)
	Find(ctx context.Context, pair *queryWrapper.WherePair) ([]*model.IndexImg, error)
	Updates(ctx context.Context, indexImg *model.IndexImg, oldPic string) error
	DeleteBatch(context.Context, []uint) error
}

type IndexImgService struct {
	db                *gorm.DB
	repository        repository.IIndexImgRepository
	attachFileService IAttachFileService
	redisClient       cache.IRedisIndexImgCache
}

func NewIndexImgService(attachFileService IAttachFileService, repository repository.IIndexImgRepository) IIndexImgService {
	return &IndexImgService{variables.GormDB(), repository, attachFileService, cache.NewRedisIndexImgCache()}
}

func (s *IndexImgService) Create(ctx context.Context, indexImg *model.IndexImg) error {
	return s.db.Transaction(func(tx *gorm.DB) error {
		if indexImg.FileId > 0 {
			if err := s.attachFileService.UpdateBatchAttachFileStatus(ctx, tx, []uint{indexImg.FileId}, constant.FILE_NORMAL); err != nil {
				return err
			}
		}
		if err := s.repository.Create(tx, indexImg); err != nil {
			variables.Logger.Errorf(ctx, "create indexImg failed: err %v, indexImg %+v", err, indexImg)
			return err
		}

		_ = s.redisClient.Remove()
		return nil
	})
}

func (s *IndexImgService) FindPage(ctx context.Context, paginator *pagehelper.Paginator) (*pagehelper.Record, error) {
	count, err := s.repository.Count(s.db, paginator.Params)
	if err != nil {
		variables.Logger.Errorf(ctx, "find indexImg to count failed: err %v, params %+v", err, paginator.Params)
		return paginator.Record, err
	}

	if count == 0 {
		return paginator.Record, nil
	}

	page, err := s.repository.FindPage(s.db, paginator.Params)
	if err != nil {
		variables.Logger.Errorf(ctx, "find indexImg to page: err: %v, params %+v", err, paginator.Params)
		return paginator.Record, err
	}

	paginator.Count(count).Record.List = page

	return paginator.Record, nil
}

func (s *IndexImgService) FindOne(ctx context.Context, pair *queryWrapper.WherePair) (*model.IndexImg, error) {
	indexImg, err := s.repository.FindOne(s.db, pair)
	if err != nil || !errors.Is(gorm.ErrRecordNotFound, err) {
		variables.Logger.Errorf(ctx, "findOne indexImg failed: err %v", err)
		return nil, err
	}

	return indexImg, nil
}

func (s *IndexImgService) FindById(ctx context.Context, imgId uint) (*model.IndexImg, error) {
	indexImg, err := s.repository.FindById(s.db, imgId)
	if err != nil {
		variables.Logger.Errorf(ctx, "findById index failed: err %v, imgId %d", err, imgId)
		return nil, err
	}
	return indexImg, nil
}

func (s *IndexImgService) Updates(ctx context.Context, indexImg *model.IndexImg, oldPic string) error {
	columns := map[string]interface{}{
		"pic":        indexImg.Pic,
		"des":        indexImg.Des,
		"title":      indexImg.Title,
		"link":       indexImg.Link,
		"status":     indexImg.Status,
		"seq":        indexImg.Seq,
		"type":       indexImg.Type,
		"relation":   indexImg.Relation,
		"prod_name":  indexImg.ProdName,
		"updated_at": time.Now(),
	}

	err := s.repository.Updates(s.db, indexImg.ImgId, columns)
	if err != nil {
		variables.Logger.Errorf(ctx, "updates indexImg failed: err %v, columns %+v", err, columns)
		return err
	}

	// 删除旧图片
	if oldPic != "" {
		if err := s.attachFileService.DeleteBatchExpire(ctx, []string{oldPic}); err != nil {
			return err
		}
	}

	// 新图片
	if indexImg.FileId > 0 {
		// 正常
		if err := s.attachFileService.UpdateBatchAttachFileStatus(ctx, s.db, []uint{indexImg.FileId}, constant.FILE_NORMAL); err != nil {
			return err
		}
	}

	_ = s.redisClient.Remove()
	return nil
}

func (s *IndexImgService) DeleteBatch(ctx context.Context, ids []uint) error {
	err := s.repository.DeleteBatch(s.db, ids)
	if err != nil {
		variables.Logger.Errorf(ctx, "deleteBatch indexImg failed: err %v, ids %s", err, ids)
		return err
	}
	_ = s.redisClient.Remove()
	return nil
}

func (s *IndexImgService) Find(ctx context.Context, pair *queryWrapper.WherePair) ([]*model.IndexImg, error) {
	cacheData, err := s.redisClient.GetCache()
	if len(cacheData) > 0 && err == nil {
		return cacheData, nil
	}

	list, err := s.repository.Find(s.db, pair)

	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		variables.Logger.Errorf(ctx, "find indexImg failed: err %v, pair %+v", err, pair)
		return nil, err
	}

	if err := s.redisClient.PutCache(list); err != nil {
		variables.Logger.Errorf(ctx, "cache set indexImgs failed: err %v", err)
	}

	return list, nil
}
